package com.pc.admin.strategy;

import com.pc.admin.annotation.Limiting;
import com.pc.admin.entity.FrequencyEntity;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * 限流 策略 抽象
 * ps:新增限流策略类 类上必须有@AutoFrequency注解
 *
 * @author <a href="https://www.lvfeiy.top">lfy</a>
 * @date 2023/6/23 11:22
 */
public abstract class FrequencyStrategy {
    private final static String IP_NULL = "unknown";
    /**
     * 策略入口
     * @return 是否进入此策略
     */
    public abstract boolean analysis(Limiting.Target target);

    /**
     * 分支逻辑
     * @param limiting 限流注解
     */
    public abstract FrequencyEntity service(Limiting limiting, ProceedingJoinPoint joinPoint);

    /**
     * @return 策略名
     */
    public abstract String getName();


    /**
     * 主逻辑 模板方法模式
     * @param limiting 限流注解
     * @param supplier 分支策略
     * @return 构建某个实体
     */
    protected <T>T asbService(Limiting limiting, Supplier<T> supplier){

        //时间转换（秒）
        int time = limiting.time();
        int num = limiting.num();

        TimeUnit timeUnit = limiting.TIME_UNIT();
        long period = timeUnit.toSeconds(time);

        //当前时间(毫秒)
        long nowTime = System.currentTimeMillis();
        FrequencyEntity frequencyEntity = new FrequencyEntity();
        frequencyEntity.setPeriod(period);
        frequencyEntity.setNowTime(nowTime);
        frequencyEntity.setNum(num);
        //key
       return supplier.ggBeng(frequencyEntity);

    }

    protected String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || IP_NULL.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || IP_NULL.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || IP_NULL.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || IP_NULL.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || IP_NULL.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    @FunctionalInterface
    protected interface Supplier<T>{
        /**
         * 模板设计模式 根据不同策略解析不同key
         * @param frequencyEntity 限流信息载体实体类
         * @return T
         */
        T ggBeng(FrequencyEntity frequencyEntity);
    }
}
